/*
 * @Author: 晴鸢. 3013433857@qq.com
 * @Date: 2025-09-23 11:54:28
 * @LastEditors: 晴鸢. 3013433857@qq.com
 * @LastEditTime: 2025-09-24 17:14:54
 * @FilePath: /Learn/blockqueue/blockqueue.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include<iostream>
#include<unistd.h>
#include<pthread.h>
#include<queue>
using namespace std;
template<class T>
class BlockQueue
{
    static const int defalutnum=5;
public:
    BlockQueue(int maxcap=defalutnum)
        :_maxcap(maxcap)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&c_cond,nullptr);
        pthread_cond_init(&p_cond,nullptr);
        low_water=_maxcap/3;
        high_water=(_maxcap*2)/3;
    }
    T pop()
    {
        pthread_mutex_lock(&_mutex);
        //判断生产条件是否满足要在加锁之后，因为判断条件本身就是临界资源
        //在加锁前判断可能会引发一系列问题
        while(_q.size()==0)//同while防止线程会有伪唤醒的情况
        {
            //进入等待队列
            pthread_cond_wait(&c_cond,&_mutex);
        }
        T out=_q.front();
        _q.pop();
        //消费者一旦消费，说明有多余的空间
        if(_q.size()<low_water) //剩余空间较多，让生产者生产
            pthread_cond_signal(&p_cond);
        pthread_mutex_unlock(&_mutex);
        return out;
    }

    void push(const T&in)
    {
        pthread_mutex_lock(&_mutex);
        //判断生产条件是否满足要在加锁之后，因为判断条件本事就是临界资源
        //在加锁前判断可能会引发一系列问题
        while(_q.size()==_maxcap)//用while防止线程会有伪唤醒的情况
        {
            pthread_cond_wait(&p_cond,&_mutex);
        }
        //生产之前需要确保生产条件满足
        _q.push(in);
        //生产者一旦有数据，即可唤醒消费者的等待队列
        if(_q.size()>high_water)
        //有充足的资源，让消费者消费
            pthread_cond_signal(&c_cond);
        pthread_mutex_unlock(&_mutex);
    }
    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&c_cond);
        pthread_cond_destroy(&p_cond);
    }
private:
    std::queue<T>_q;
    int _maxcap; //队列的最大值
    pthread_mutex_t _mutex;// 锁保护临界资源
    //用来区分消费者和生产者的等待队列
    pthread_cond_t c_cond;//条件变量
    pthread_cond_t p_cond;//条件变量
    //控制生产和消费的条件
    int low_water;
    int high_water;
};